<template>
  <div class="chat-container">
    <div class="chat-header">
      <div class="back-line" v-if="backToHome">
        <router-link class="link" to="/">← 返回首页</router-link>
      </div>
      <div class="title-row">
        <div class="title">{{ title }}</div>
        <div class="chat-id" v-if="chatId">ID: {{ chatId }}</div>
      </div>
    </div>

    <div class="chat-history" ref="historyRef">
      <div v-for="(msg, idx) in messages" :key="idx" :class="['msg', msg.role]">
        <img v-if="msg.role==='ai'" class="avatar" :src="aiAvatar" alt="ai" />
        <div class="bubble" v-html="renderContent(msg)"></div>
      </div>
    </div>

    <form class="chat-input" @submit.prevent="onSend">
      <input v-model="input" type="text" placeholder="请输入内容..." />
      <button :disabled="loading">{{ loading ? '发送中...' : '发送' }}</button>
    </form>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { marked } from 'marked'
import DOMPurify from 'dompurify'

interface Message {
  role: 'user' | 'ai'
  content: string
}

const props = defineProps<{
  title: string
  chatId?: string
  sseUrl: string
  queryBuilder: (message: string, chatId?: string) => string
  isHtml?: boolean
  aiAvatar?: string
  appendNewlinePerEvent?: boolean
  backToHome?: boolean
}>()

const input = ref('')
const loading = ref(false)
const messages = reactive<Message[]>([])
const historyRef = ref<HTMLDivElement | null>(null)
let es: EventSource | null = null

function appendMessage(role: Message['role'], content: string) {
  messages.push({ role, content })
  // 滚动到底部
  requestAnimationFrame(() => {
    historyRef.value?.scrollTo({ top: historyRef.value.scrollHeight, behavior: 'smooth' })
  })
}

function renderContent(m: Message) {
  if (m.role === 'ai') {
    // 转 Markdown 为 HTML，并做 XSS 过滤
    const html = marked.parse(m.content ?? '') as string
    return DOMPurify.sanitize(html)
  }
  return DOMPurify.sanitize(m.content)
}

function closeStream() {
  if (es) {
    es.close()
    es = null
  }
}

function onSend() {
  if (!input.value.trim() || loading.value) return
  const text = input.value
  input.value = ''
  appendMessage('user', text)
  loading.value = true

  closeStream()
  const url = props.queryBuilder(text, props.chatId)
  es = new EventSource(url)
  let buffer = ''

  es.onmessage = (evt) => {
    const data = evt.data
    if (buffer === '') {
      appendMessage('ai', '')
    }
    const chunk = props.appendNewlinePerEvent ? (data + '\n') : data
    buffer += chunk
    messages[messages.length - 1].content = buffer
  }

  es.onerror = () => {
    loading.value = false
    closeStream()
  }

  es.onopen = () => {
    // no-op
  }

  // 完成由后端控制（SSE流结束即完成）
  // 这里简单在错误或手动关闭时复位
  const stop = () => { loading.value = false }
  setTimeout(stop, 0)
}

onUnmounted(() => closeStream())

onMounted(() => {
  // 初次进入不自动发消息
})
</script>

<style scoped>
.chat-container { display: flex; flex-direction: column; height: calc(100vh - var(--header-h)); max-width: 860px; margin: 0 auto; }
.chat-header { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; border-bottom: 1px solid #eee; }
.back-line{ width: 100%; margin-bottom: 6px; }
.title-row{ width: 100%; display: flex; justify-content: space-between; align-items: center; }
.title { font-weight: 600; }
.chat-id { color: #888; font-size: 12px; }
.chat-history { flex: 1; overflow-y: auto; padding: 16px; background: #fafafa; }
.msg { display: flex; gap: 8px; margin-bottom: 12px; align-items: flex-start; }
.msg.user { justify-content: flex-end; }
.msg.ai { justify-content: flex-start; }
.avatar{ width: 32px; height: 32px; border-radius: 50%; margin-top: 4px; }
.bubble { max-width: 72%; padding: 10px 12px; border-radius: 10px; white-space: pre-wrap; line-height: 1.7; }
.msg.user .bubble { background: #1f87ff; color: #fff; border-bottom-right-radius: 2px; }
.msg.ai .bubble { background: #fff; color: #222; border-bottom-left-radius: 2px; box-shadow: 0 1px 2px rgba(0,0,0,.06); }
.chat-input { display: flex; gap: 8px; padding: 12px; border-top: 1px solid #eee; }
.chat-input input { flex: 1; padding: 10px 12px; border: 1px solid #ddd; border-radius: 6px; outline: none; }
.chat-input button { padding: 10px 16px; border: none; border-radius: 6px; background: #1f87ff; color: #fff; cursor: pointer; }
.chat-input button:disabled { opacity: .6; cursor: not-allowed; }
</style>
